﻿#ifndef BLUETOOTHCTRL_H
#define BLUETOOTHCTRL_H

#include <QObject>
//#include <QQuickItem>
#include <QtBluetooth/QtBluetooth>
#include "QtChCharset.h"


class BluetoothDeviceModel;
class LowEnergyInfoModel;

class BluetoothCtrl : public QObject
{
    Q_OBJECT
public:
    enum EnumBluetoothState
    {
        BluetoothState_NoScan,

        BluetoothState_localConnected,
        BluetoothState_localDisconnected,

        BluetoothState_DeviceStart,
        BluetoothState_DeviceNewDiscovered,
        BluetoothState_DeviceEnd,
        //BluetoothState_DeviceError,
        BluetoothState_DeviceCancel,

        BluetoothState_ServiceStart,
        BluetoothState_ServiceNewDiscovered,
        BluetoothState_ServiceEnd,
        BluetoothState_ServiceEndAllDevice,
        //BluetoothState_ServiceError,
        BluetoothState_ServiceCancel,

        BluetoothState_SocketConnectStart,
        BluetoothState_SocketConnected,
        BluetoothState_SocketDisconnected,
        //BluetoothState_SocketError,

        BluetoothState_LowEnergyConnectStart,
        BluetoothState_LowEnergyConnected,
        BluetoothState_LowEnergyDisconnected,
        BluetoothState_LowEnergyDiscoverServiceStart,
        BluetoothState_LowEnergyDiscoverNewService,
        BluetoothState_LowEnergyDiscoverDetails,
        //BluetoothState_LowEnergyError,

        // localBluetooth错误
        BluetoothState_LocalBluetoothPairingError,
        BluetoothState_LocalBluetoothUnknownError,
        // DeviceDiscoveryAgent错误和ServiceDiscoveryAgent错误
        BluetoothState_InputOutputError,
        BluetoothState_PoweredOffError,
        BluetoothState_InvalidBluetoothAdapterError,
        BluetoothState_UnsupportedPlatformError,
        BluetoothState_UnsupportedDiscoveryMethod,
        BluetoothState_DeviceDiscoveryAgentUnknownError,
        BluetoothState_BluetoothServiceUnknownError,
        // socket错误
        BluetoothState_UnknownSocketError,
        BluetoothState_RemoteHostClosedError,
        BluetoothState_HostNotFoundError,
        BluetoothState_ServiceNotFoundError,
        BluetoothState_NetworkError,
        BluetoothState_UnsupportedProtocolError,
        BluetoothState_OperationError,
        // LowEnergyController错误
        BluetoothState_LowEnergyCtrlUnknownError,
        BluetoothState_LowEnergyCtrlUnknownRemoteDeviceError,
        BluetoothState_LowEnergyCtrlNetworkError,
        BluetoothState_LowEnergyCtrlInvalidBluetoothAdapterError,
        BluetoothState_LowEnergyCtrlConnectionError,
        BluetoothState_LowEnergyCtrlAdvertisingError,
        BluetoothState_LowEnergyCtrlRemoteHostClosedError,
        // LowEnergyService错误
        BluetoothState_LowEnergyServiceOperationError,
        BluetoothState_LowEnergyServiceCharacteristicWriteError,
        BluetoothState_LowEnergyServiceDescriptorWriteError,
        BluetoothState_LowEnergyServiceUnknownError,
        BluetoothState_LowEnergyServiceCharacteristicReadError,
        BluetoothState_LowEnergyServiceDescriptorReadError,

    };
    Q_ENUM(EnumBluetoothState)

    enum EnumCharset {
        EnumCharset_HEX = 0,
        EnumCharset_GBK,
        EnumCharset_UTF8,
        EnumCharset_UNICODE,
    };
    Q_ENUM(EnumCharset)
public:
    explicit BluetoothCtrl(QObject *parent = nullptr);
public:
    static BluetoothCtrl * singleton();
Q_SIGNALS:
    // 蓝牙状态改变
    void signalBluetoothState(EnumBluetoothState newState);
    // 蓝牙接收到数据
    void signalReceiveData(QByteArray byteData);
    void signalReceiveString(QString strData);
    // 单次收发字节长度
    void signalReceiveByteLength(int byteLength);
    void signalSendByteLength(int byteLength);
public Q_SLOTS:
    // 本地蓝牙---------------------------------------------------------------------------
    void localBluetoothHostModeStateChanged(QBluetoothLocalDevice::HostMode state);
    void localBluetoothDeviceConnected(const QBluetoothAddress &address);
    void localBluetoothDeviceDisconnected(const QBluetoothAddress &address);
    void localBluetoothPairingFinished(const QBluetoothAddress &address, QBluetoothLocalDevice::Pairing pairing);
    void localBluetoothPairingDisplayPinCode(const QBluetoothAddress &address, QString pin);
    void localBluetoothPairingDisplayConfirmation(const QBluetoothAddress &address, QString pin);
    void localBluetoothError(QBluetoothLocalDevice::Error error);
    // 蓝牙设备扫描-------------------------------------------------------------------------
    void deviceDiscoveryAgentDeviceDiscovered(const QBluetoothDeviceInfo &info);
    void deviceDiscoveryAgentDeviceUpdated(const QBluetoothDeviceInfo &info, QBluetoothDeviceInfo::Fields updatedFields);
    void deviceDiscoveryAgentDiscoveredFinished();
    void deviceDiscoveryAgentError(QBluetoothDeviceDiscoveryAgent::Error error);
    void deviceDiscoveryAgentCanceled();
    // 开始设备扫描
    bool startDeviceScan();
    bool stopDeviceScan();
    // 设备过滤
    void setDeviceFilter(const QString& filter);
    QString getDeviceFilter();
    // 蓝牙服务扫描--------------------------------------------------------------------------
    void serviceDiscovered(const QBluetoothServiceInfo &info);
    void serviceDiscoveryFinished();
    void serviceError(QBluetoothServiceDiscoveryAgent::Error error);
    void serviceDiscoveryCanceled();
    // 开始蓝牙服务扫描
    bool startServiceScan();
    bool startServiceScan(const QBluetoothAddress &address);
    bool startServiceScanFromDiscoveredDeviceList();
    bool stopServiceScan();
    // 蓝牙socket-----------------------------------------------------------------------------
    void bluetoothSocketConnected();
    void bluetoothSocketDisconnected();
    void bluetoothSocketError(QBluetoothSocket::SocketError error);
    void bluetoothSocketStateChanged(QBluetoothSocket::SocketState state);
    void bluetoothSocketReadyRead();
    //void channelReadyRead(int channel);
    void bluetoothSocketBytesWritten(qint64 bytes);
    //void channelBytesWritten(int channel, qint64 bytes);
    //void aboutToClose();
    //void readChannelFinished();
    // 连接蓝牙socket
    bool connectSocket(const QBluetoothServiceInfo &service);
    bool connectSocket(const QString &address, const QString& uuid, int socketProtocol);
    bool disconnectSocket();
    // 低功耗蓝牙-----------------------------------------------------------------------------
    // 低功耗蓝牙连接和状态改变
    void lowEnergyCtrlConnected();
    void lowEnergyCtrlDisconnected();
    void lowEnergyCtrlStateChanged(QLowEnergyController::ControllerState state);
    void lowEnergyCtrlError(QLowEnergyController::Error newError);
    // 低功耗蓝牙服务扫描
    void lowEnergyCtrlServiceDiscovered(const QBluetoothUuid &newService);
    void lowEnergyCtrlDiscoveryFinished();
    void lowEnergyCtrlConnectionUpdated(const QLowEnergyConnectionParameters &parameters);
    // 低功耗蓝牙服务
    void lowEnergyServiceStateChanged(QLowEnergyService::ServiceState newState);
    void lowEnergyServiceCharacteristicChanged(const QLowEnergyCharacteristic &info, const QByteArray &value);
    void lowEnergyServiceCharacteristicRead(const QLowEnergyCharacteristic &info, const QByteArray &value);
    void lowEnergyServiceCharacteristicWritten(const QLowEnergyCharacteristic &info, const QByteArray &value);
    void lowEnergyServiceDescriptorRead(const QLowEnergyDescriptor &info, const QByteArray &value);
    void lowEnergyServiceDescriptorWritten(const QLowEnergyDescriptor &info, const QByteArray &value);
    void lowEnergyServiceError(QLowEnergyService::ServiceError error);
    // 连接低功耗蓝牙
    bool connectLowEnergyDevice(const QString &lowEnergyDeviceAddr);
    bool disconnectLowEnergyDevice();
    // 选择指定的characteristic用于发送
    bool selectLowEnergyCharacteristic(const QString& characteristicName, const QString& characteristicUuid, const QString& serviceName, const QString& serviceUuid);
    bool readLowEnergyCharacteristic(const QString& characteristicName, const QString& characteristicUuid, const QString& serviceName, const QString& serviceUuid);
    // 写descriptor
    bool writeLowEnergyDescriptor(const QString& descriptorName, const QString& descriptorUuid, const QString& characteristicUuid, const QString& serviceUuid, QString strData, EnumCharset charset);
    bool readLowEnergyDescriptor(const QString& descriptorName, const QString& descriptorUuid, const QString& characteristicUuid, const QString& serviceUuid);
public slots:
    // 开始扫描
    bool startScan();
    // 发送数据
    bool sendData(QString data, EnumCharset charset);
    // 设置接收数据类型
    void setReceiveCharsetType(EnumCharset charset);
    // 设置列表模型指针
    void setBluetoothDeviceModel(BluetoothDeviceModel *model);
    void setLowEnergyInfoModel(LowEnergyInfoModel *model);
public:
    // 读取本地蓝牙信息
    Q_INVOKABLE QVariantMap getLocalDeviceInfo();
private:
    // 字节数组转字符串
    QString byteArrayToString(const QByteArray& byteArray);
    // 字符串按指定编码转成byteArray
    bool StringToByteArray(const QString& strData, EnumCharset charset, QByteArray& byteData);
    // 统一处理接收数据
    void ProcessReceiveData(const QByteArray& rxData);
private:
    // 本地蓝牙设备
    QBluetoothLocalDevice mLocalBluetooth;
    // 蓝牙设备扫描代理
    QBluetoothDeviceDiscoveryAgent mDeviceDiscoveryAgent;
    QString mstrDeviceFilter;
    // 蓝牙服务扫描代理
    QBluetoothServiceDiscoveryAgent mServiceDiscoveryAgent;
    // 打开蓝牙服务的socket
    QSharedPointer<QBluetoothSocket> mpBluetoothSocket;
    //QBluetoothSocket *mpBluetoothSocket = nullptr;
    QString mSocketPeerAddress;
    QString mSocketPeerServiceUUID;
    int mSocketPeerProtocol = 0;

    // 低功耗蓝牙
    QSharedPointer<QLowEnergyController> mpLowEnergyCtrl;
    //QLowEnergyController *mpLowEnergyCtrl = nullptr;
    //QSharedPointer<QLowEnergyService> mpLowEnergyService;
    //QLowEnergyService *mpLowEnergyService = nullptr;
    QList<QSharedPointer<QLowEnergyService>> mLowEnergyServiceList;
    int miDiscoverDetailsIndex = -1;
    bool lowEnergyServiceDiscoverDetails();

    QSharedPointer<QLowEnergyService> mpLowEnergyServiceSelected;
    QString strCharacteristicUuidSelected;


    // 扫描发现的设备
    QList<QBluetoothDeviceInfo> mDiscoveredDeviceList;
    // 显示的列表模型对象
    BluetoothDeviceModel *mDeviceModel = nullptr;
    // 显示的列表模型对象
    LowEnergyInfoModel *mLowEnergyModel = nullptr;

    // 接收数据类型
    EnumCharset mRxCharset = EnumCharset_GBK;
};

#endif // BLUETOOTHCTRL_H
